//
//  _objc_msgForward.h
//  面试题
//
//  Created by Toj on 8/15/21.
//

// 消息没有处理, 做消息转发
{
    STATIC_ENTRY __objc_msgForward_impcache

    MESSENGER_START
    nop
    MESSENGER_END_SLOW

    // 跳转 _objc_msgForward
    b    __objc_msgForward

    END_ENTRY __objc_msgForward_impcache
}

// 消息没有处理
{
    ENTRY __objc_msgForward

    adrp    x17, __objc_forward_handler@PAGE
    ldr    x17, [x17, __objc_forward_handler@PAGEOFF]
    br    x17

    END_ENTRY __objc_msgForward
}

// objc_setForwardHandler 没找到源码
// 我们根据函数调用栈分析 + Hopper分析 CoreFoundation里函数的伪代码

 UIKitCore -[UIResponder doesNotRecognizeSelector:] + 292
 CF        ___forwarding___ + 1455
 CF        _CF_forwarding_prep_0 + 120

int ___forwarding_prep_0___(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
    *(rsp + 0xa0) = zero_extend_64(xmm7);
    *(rsp + 0x90) = zero_extend_64(xmm6);
    *(rsp + 0x80) = zero_extend_64(xmm5);
    *(rsp + 0x70) = zero_extend_64(xmm4);
    *(rsp + 0x60) = zero_extend_64(xmm3);
    *(rsp + 0x50) = zero_extend_64(xmm2);
    *(rsp + 0x40) = zero_extend_64(xmm1);
    *(rsp + 0x30) = zero_extend_64(xmm0);
    stack[2021] = arg0;
    rax = ____forwarding___(rsp, 0x0);
    if (rax != 0x0) {
            rax = *rax;
    }
    else {
            rax = objc_msgSend(stack[2021], stack[2021]);
    }
    return rax;
}

// ____forwarding___
function ____forwarding___ {
    r13 = rsi;
    r15 = rdi;
    var_-48 = *___stack_chk_guard;
    rcx = COND_BYTE_SET(NE);
    if (rsi == 0x0) {
            r12 = _objc_msgSend;
    }
    else {
            r12 = _objc_msgSend_stret;
    }
    var_-312 = rcx * 0x8;
    rbx = *(r15 + rcx * 0x8);
    rdx = *(r15 + rcx * 0x8 + 0x8);
    if (rbx >= 0x0)
        goto loc_115fb4;
}

// loc_115fb4: forwardingTargetForSelector
{
loc_115fb4:
    var_150 = r12;
    var_140 = rdx;
    var_148 = r15;
    rax = object_getClass(rbx);
    r15 = rax;
    r12 = class_getName(rax);
    r14 = @selector(forwardingTargetForSelector:);
    if (class_respondsToSelector(r15, r14) == 0x0)
        goto loc_116064;
}

// 方法签名 & 二次转发
{
    
    0000000000116087         mov        rbx, qword [0x598e90]                  @selector(methodSignatureForSelector:)
    000000000011608e         mov        rdi, r15
    argument "cls" for method imp___stubs__class_respondsToSelector
    0000000000116091         mov        rsi, rbx
    argument "sel" for method imp___stubs__class_respondsToSelector
    0000000000116094         call       imp___stubs__class_respondsToSelector
    0000000000116099         test       al, al
    000000000011609b         mov        r14, qword [rbp+var_138]
    00000000001160a2         je         loc_1163e3
        
      //  forwardInvocation
        00000000001161fe         mov        qword [rbp+var_150], r12
    CODE XREF=____forwarding___+557
        0000000000116205         mov        rdi, r14
    argument "obj" for method imp___stubs__object_getClass
        0000000000116208         call       imp___stubs__object_getClass
        000000000011620d         mov        r12, r14
        0000000000116210         mov        r14, qword [0x598ef0]
        @selector(forwardInvocation:)
        0000000000116217         mov        rdi, rax
    argument "cls" for method imp___stubs__class_respondsToSelector
        000000000011621a         mov        rsi, r14
    argument "sel" for method imp___stubs__class_respondsToSelector
        000000000011621d         call       imp___stubs__class_respondsToSelector
        0000000000116222         test       al, al
        0000000000116224         je         loc_11642b
}

// loc_116064:
{
loc_116064:
    var_-312 = rbx;
    if (strncmp(r12, "_NSZombie_", 0xa) == 0x0)
        goto loc_1163cd;
}

// loc_1163cd
{
loc_1163cd:
    ____forwarding___.cold.2(var_-312, r12, var_-320);
    goto loc_1163e3;
}

// loc_1163e3
// 消息转发都没有处理调用的函数
// Default forward handler halts the process.
// 默认终止程序
{
loc_1163e3:
    rbx = class_getSuperclass(r15);
    r14 = object_getClassName(r14);
    if (rbx == 0x0) {
            _CFLog(0x4, @"*** NSForwarding: warning: object %p of class '%s' does not implement methodSignatureForSelector: -- did you forget to declare the superclass of '%s'?", var_-312, r14, object_getClassName(var_-312));
    }
    else {
            _CFLog(0x4, @"*** NSForwarding: warning: object %p of class '%s' does not implement methodSignatureForSelector: -- trouble ahead", var_-312, r14);
    }
    goto loc_116457;
}

// loc_116457
{
loc_116457:
    rbx = var_-320;
    goto loc_11645e;
}

// loc_11645e
{
loc_11645e:
    rax = sel_getName(rbx);
    r14 = rax;
    rax = sel_getUid(rax);
    if (rax != rbx) {
            r8 = rax;
            _CFLog(0x4, @"*** NSForwarding: warning: selector (%p) for message '%s' does not match selector known to Objective C runtime (%p)-- abort", var_-320, r14, r8);
    }
    rbx = @selector(doesNotRecognizeSelector:);
    if (class_respondsToSelector(object_getClass(var_-312), rbx) == 0x0)
        goto loc_1164d1;
}

// loc_1164d1
{
loc_1164d1:
    ____forwarding___.cold.3(var_-312);
    goto loc_1164dd;
}

// loc_1164dd
{
loc_1164dd:
    ____forwarding___.cold.1();
    rax = objc_opt_class(@class(NSInvocation));
    *____forwarding___.invClass = rax;
    rax = class_getInstanceSize(rax);
    *____forwarding___.invClassSize = rax;
    return rax;
}
